package com.woodws.core.data;

import com.slyak.spring.jpa.OV;
import com.slyak.spring.jpa.OVMap;
import com.slyak.spring.jpa.PageParams;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;

import java.io.Serializable;
import java.util.Map;

public class PageParamsImpl extends OVMap implements PageParams {

    private static final long serialVersionUID = -4541509938956089562L;
    private Sort sort;
    private int page;
    private int size;
    private boolean isPaging = false;


    public int getPageSize() {
        return this.size;
    }

    public int getPageNumber() {
        return this.page;
    }

    public long getOffset() {
        return this.page * this.size;
    }

    public boolean hasPrevious() {
        return this.page > 0;
    }

    public Pageable previousOrFirst() {
        return this.hasPrevious() ? this.previous() : this.first();
    }

    public PageParamsImpl() {

    }

    public PageParamsImpl(int page, int size) {
        this(page, size, (Sort)null);
    }

    public PageParamsImpl(int page, int size, Sort.Direction direction, String... properties) {
        this(page, size, new Sort(direction, properties));
    }

    public PageParamsImpl(int page, int size, Sort sort) {
        isPaging = true;
        if (page < 0) {
            throw new IllegalArgumentException("Page index must not be less than zero!");
        } else if (size < 1) {
            throw new IllegalArgumentException("Page size must not be less than one!");
        } else {
            this.page = page;
            this.size = size;
        }
        this.sort = sort;
    }

    public void setSort(String... properties) {
        this.sort = new Sort(properties);
    }

    public void setSort(Sort sort) {
        this.sort = sort;
    }

    public Sort getSort() {
        return this.sort;
    }

    public Pageable next() {
        return new PageParamsImpl(this.getPageNumber() + 1, this.getPageSize(), this.getSort());
    }

    public PageParamsImpl previous() {
        return this.getPageNumber() == 0 ? this : new PageParamsImpl(this.getPageNumber() - 1, this.getPageSize(), this.getSort());
    }

    public Pageable first() {
        return new PageParamsImpl(0, this.getPageSize(), this.getSort());
    }

    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        } else if (!(obj instanceof PageParamsImpl)) {
            return false;
        } else {
            PageParamsImpl that = (PageParamsImpl)obj;
            boolean sortEqual = this.sort == null ? that.sort == null : this.sort.equals(that.sort);
            return super.equals(that) && sortEqual;
        }
    }

    public int hashCode() {
        return 31 * super.hashCode() + (null == this.sort ? 0 : this.sort.hashCode());
    }

    public String toString() {
        return String.format("Page request [number: %d, size %d, sort: %s]", this.getPageNumber(), this.getPageSize(), this.sort == null ? null : this.sort.toString());
    }

    @Override
    public boolean isPaging() {
        return isPaging;
    }

    public void addParams(OV ov){
        this.putAll((OVMap) ov);
    }

    @Override
    public void addParams(Map map) {
        this.putAll(map);
    }
}
